import Coordinate from '../../components/tile/Coordinate.js'
import PieceProcess from '../../components/tile/PieceProcess.js'
import Grid from '../../components/tile/Grid.js'
import Utils from './util/utils.js'

// 常量定义
const NONE = 0
const BLACK = 1
const WHITE = 2
const FLAG = 3
const BLACK_PRE = 4;
const WHITE_PRE = 5;

export default class Board {

  constructor() {
    this.boardSize = 19
    this.hasPickother = false
    this.hasPickStone = false
    this.pieces = []
    this.piecesOrigin = []
    this.piecesOriginTemp = []
    this.piecesTry = []
    this.piecesTryTemp = []
    this.currentGrid = new Grid()
    this.nextColor = BLACK
    this.nextColorTemp = -1
    this.isTrying = false
    this.isReviewing = false
    this.bwtag = 0
    this.piecesener = null
    this.bGobanging = false
    this.utils = new Utils()
    this.listeners = []
  }

  // 添加监听器
  addListener(listener) {
    this.listeners.push(listener)
  }

  // 移除监听器
  removeListener(listener) {
    const index = this.listeners.indexOf(listener);
    if (index !== -1) {
      this.listeners.splice(index, 1);
    }
  }

  // 通知所有监听器
  notifyListeners(frame, change) {
    this.listeners.forEach(listener => {
      listener(frame, change);
    });
  }

  enterReviewMode() {
    this.isReviewing = true
    this.piecesOriginTemp = []
    this.piecesOrigin=[]
    this.piecesOrigin = this.piecesOrigin.concat(this.pieces)
    this.piecesOriginTemp = this.piecesOriginTemp.concat(this.pieces)
    // Array.prototype.push.apply(this.piecesOrigin, this.pieces);
    // Array.prototype.push.apply(this.piecesOriginTemp, this.pieces);
  }

  exitTry() {
    this.isTrying = false
    this.piecesTryTemp = []
    this.piecesTry = []
    this.refreshPieces(this.piecesOriginTemp)
    this.nextColor = this.nextColorTemp
  }


  enterTry() {
    this.isTrying = true
    this.nextColorTemp = this.nextColor
  }

  getChessValue(x, y) {
    return this.currentGrid.getChessValue(x, y);
  }

  setChessValue(x, y, value) {
    this.currentGrid.setChessValue(x, y, value);
  }

  // 连续落子
  continueput(x, y, bwtag) {
    const c = new Coordinate(x, y)
    const p = new PieceProcess(bwtag, c, this.boardSize)

    if (x === 0 && y === 0) {
      return false
    }

    if (this.currentGrid.putPiece(p)) {
      if (!this.check(p)) {
        this.currentGrid.executePieceProcess(p, true)
        return false
      }

      if (p.bw !== FLAG) {
        this.pieces.push(p)
      }
      this.nochangefinishPut()
      return true
    }
    return false
  }

  // 不考虑提子的连续落子
  continueputNoPick(x, y, bwtag) {
    const c = new Coordinate(x, y)
    const p = new PieceProcess(bwtag, c, this.boardSize)

    if (x === 0 && y === 0) {
      return false
    }

    if (this.currentGrid.putPieceNoPick(p)) {
      if (!this.check(p)) {
        this.currentGrid.executePieceProcess(p, true)
        return false
      }

      if (p.bw !== FLAG) {
        this.pieces.push(p)
      }
      this.nochangefinishPut()
      return true
    }
    return false
  }

  setNextColor(nextColor) {
    this.nextColor = nextColor;
  }

  getNextColor() {
    return this.nextColor
  }

  // 落子
  put(bw, x, y) {
    const c = new Coordinate(x, y, this.boardSize, bw)
    const p = new PieceProcess(bw, c, this.boardSize)

    if (x === 0 && y === 0) {
      if (p.bw !== FLAG) {
        this.pieces.push(p)
      }
      this.finishedPut()
      return true
    }

    // 检查当前位置是否已经有子
    if (this.getChessValue(x, y) == BLACK || this.getChessValue(x, y) == WHITE) {
      return false
    }

    if (this.currentGrid.putPiece(p)) {
      if (!this.check(p)) {
        this.currentGrid.executePieceProcess(p, true)
        return false
      }

      if (p.bw !== FLAG) {
        this.addPieces(p)
      }
      this.finishedPut()
      return true
    }
    return false
  }

  addPieces(p) {
    this.pieces.push(p)
    if (this.isTrying) {
      this.piecesTry = []
      this.piecesTry = this.piecesTry.concat(this.pieces.slice(this.piecesOriginTemp.length))
      this.piecesTryTemp = []
      this.piecesTryTemp = this.piecesTryTemp.concat(this.piecesTry)
      console.info('piecesTry1:', this.piecesTry.length);
      console.info('piecesTryTemp1:', this.piecesTryTemp.length);
    } else {
      this.piecesOrigin = []
      this.piecesOrigin = this.piecesOrigin.concat(this.pieces.slice(0, this.piecesOriginTemp.length))
      this.piecesOrigin.push(p)
      this.piecesOriginTemp = []
      this.piecesOriginTemp = this.piecesOriginTemp.concat(this.piecesOrigin)
    }
  }

  // 预落子检查
  prePut(x, y) {
    const c = new Coordinate(x, y)
    const p = new PieceProcess(this.nextColor, c, this.boardSize)

    if (this.currentGrid.putPiece(p)) {
      if (!this.check(p)) {
        this.currentGrid.executePieceProcess(p, true)
        return false
      }

      this.currentGrid.executePieceProcess(p, true)
      return true
    }
    return false
  }

  // 检查打劫
  check(p) {
    if (this.pieces.length < 3) return true
    return !this.isOverEqualse(this.pieces.length - 2, p)
  }

  isOverEqualse(position, p) {
    const board = new Board(this.boardSize);
    var list = this.pieces.slice(0, position + 1);
    for (let i = 0; i < list.length; i++) {
      board.executePieceProcess(list[i]);
    }
    return board.currentGrid === this.currentGrid;
  }

  // 执行行棋过程
  executePieceProcess(p) {
    if (p.c.x === 0 || p.c.y === 0) return;

    // 落子
    this.setChessValue(p.c.x, p.c.y, p.bw);

    // 移除被吃掉的子
    if (p.removedList && p.removedList.length > 0) {
      for (let i = 0; i < p.removedList.length; i++) {
        let item = p.removedList[i];
        this.setChessValue(item.c.x, item.c.y, 0);
      }
    }
  }


  // 清空棋盘
  cleanGrid() {
    this.currentGrid = new Grid()
    this.pieces = []
  }


  // 添加棋子记录
  addPieceProcess(p) {
    this.currentGrid.executePieceProcess(p, false)
    if (p.bw !== FLAG) {
      this.pieces.push(p)
    }
    this.finishedPut()
  }

  // 移除上一步
  removePieceProcess() {
    if (this.pieces.length === 0) return
    const p = this.pieces.pop()
    this.currentGrid.executePieceProcess(p, true)
    this.finishedPut()
  }

  // 获取棋盘位置值
  getValue(x, y) {
    return this.currentGrid.getValue(new Coordinate(x, y))
  }

  // 获取最后落子位置
  getLastPosition() {
    if (this.pieces.length === 0) return null
    return this.pieces[this.pieces.length - 1].c
  }

  // 获取当前手数
  getCount() {
    return this.pieces.length
  }

  // 获取试下的棋步数
  getTryCount() {
    return this.piecesTryTemp.length
  }

  // 
  getTryCountTotal() {
    return this.piecesTry.length
  }

  isFirst(){
    return this.getCount() === 0
  }

  isLast() {
    return this.getCount() === this.piecesOrigin.length
  }

  // 获取指定步数记录
  getPieceProcess(i) {
    if (i >= this.getCount() || i < 0) return null
    return this.pieces[i]
  }

  // 获取当前行棋方
  getCurBW() {
    return this.nextColor === BLACK ? '+' : '-'
  }

  // 转换为字符串表示
  toShortString(rotate, boardSize) {
    try {
      let a = ''
      const nn = this.currentGrid.getA()

      switch (rotate) {
        case 0:
          for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
              a += nn[j][i]
            }
          }
          break
        case 90:
          for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
              a += nn[i][boardSize - 1 - j]
            }
          }
          break
        case 180:
          for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
              a += nn[boardSize - 1 - j][boardSize - 1 - i]
            }
          }
          break
        case 270:
          for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
              a += nn[boardSize - 1 - i][j]
            }
          }
          break
      }
      console.log('自动生成的盘面:' + a)
      return a
    } catch (e) {
      return ''
    }
  }

  back(num) {
    if (this.isTrying) {
      this.backTry(num)
    } else {
      this.backReview(num)
    }
  }

  backReview(num) {
    // if (this.piecesOriginTemp.length - this.getCount() < num) {
    //   num = this.piecesOriginTemp.length - this.getCount()
    // }


    // 删除最后num步
    this.piecesOriginTemp.splice(
      this.piecesOriginTemp.length - num, this.piecesOriginTemp.length);


    this.refreshPieces(this.piecesOriginTemp)

  }

  backTry(num) {
    if (this.piecesTryTemp < num) {
      num = this.piecesTryTemp.length
    }

    // 删除最后的num手棋
    this.piecesTryTemp.splice(
      this.piecesTryTemp.length - num, this.piecesTryTemp.length);

    console.info('piecesTryTemp:', this.piecesTryTemp.length)

    console.info('piecesOriginTemp:', this.piecesOriginTemp.length)

    let list = [...this.piecesOriginTemp, ...this.piecesTryTemp];

    console.info('list:', list.length)

    this.refreshPieces(list)
  }

  next(num) {
    if (this.isTrying) {
      this.nextTry(num)
    } else {
      this.nextReview(num)
    }
  }

  nextReview(num) {

    if (this.piecesOrigin.length < this.piecesOriginTemp.length + num) {
      num = this.piecesOrigin.length - this.piecesOriginTemp.length
    }

    let list = this.piecesOrigin.slice(
      this.piecesOriginTemp.length,
      this.piecesOriginTemp.length + num
    );

    this.piecesOriginTemp.push(...list);


    this.refreshPieces(this.piecesOriginTemp)

  }

  nextTry(num) {
    if (this.piecesTry.length < this.piecesTryTemp.length + num) {
      num = this.piecesTry.length - this.piecesTryTemp.length
    }

    console.info('num:', num);

    let tempList = this.piecesTry.slice(
      this.piecesTryTemp.length,
      this.piecesTryTemp.length + num
    );


    this.piecesTryTemp.push(...tempList);

    let list = [...this.piecesOriginTemp, ...this.piecesTryTemp];



    this.refreshPieces(list)
  }


  // 刷新盘面
  refreshPieces(list) {
    // 清空当前棋盘
    this.currentGrid = new Grid()

    // 清空棋子数组
    this.pieces = []

    // 重置下一个颜色为黑色
    this.nextColor = BLACK;

    // 添加所有棋子
    this.pieces = this.pieces.concat(list);


    for (let i = 0; i < this.pieces.length; i++) {
      const p = this.pieces[i]
      this.executePieceProcess(p);
      this.finishedPut()
    }
  }


  finishedPut() {
    this.nextColor = this.utils.getReBW(this.nextColor)
    this.postEvent()
  }

  nochangefinishPut() {
    this.postEvent()
  }

   // 通知所有监听器
   notifyListeners(chessCount, chessTryCount) {
    this.listeners.forEach(listener => {
      listener(chessCount, chessTryCount);
    });
  }

  postEvent() {
    // this.hasPickStone = Board.hasPickother
    // if (this.piecesener) {
    //   this.piecesener(this.getCount(), this.nextColor, this.bwtag)
    // }
    this.notifyListeners(
       this.getCount(),
       this.getTryCount()
    );
  }
}